%{
#include <stdio.h>
#include <string.h>
#include <time.h>

extern char * yytext;
extern int yydebug;

#define YYERROR_VERBOSE 1 
#define YYDEBUG 1

#define YYPRINT(file, type, value) yyprint(file, type, value)

void yyerror(const char *str)
{
    fprintf(stderr,"error: %s, mystery character '%c'\n",str,*yytext);
}
 
main()
{
    yyparse();
} 

%}
                        
%union
 {
     time_t time;
     char * string;
     int    number;
     char   leter;
     struct task_list * tasks;
     struct task * task;
     struct task_header * header;
     struct task_body   * body;
     struct range {time_t from; time_t to;} range;
}

%token <number> TASK 
%token SCHEDULED CLOSED CLOCK
%token <leter> PRIORITY 
%token EOFM

%token <string> TEXT
%token <string> KEYWORD 
%token <string> DM
%token <string> NEWLINE
%token <time> DATE 
%token <time> DATEACT
%token <range> DATERANGE
%token <range> DATEACTRANGE
%token <number> CHECKBOX
%token <string> TAG

                        
%type  <number>  task_level
%type  <leter>   priority
%type  <string>  class
%type  <string>  caption
%type  <string>  text
%type  <string>  textex
%type  <string>  textnt                       
%type  <string>  string
%type  <string>  textline
%type  <string>  tagline
%type  <number>  completion

%type  <tasks>   tasks
                        
%type  <header>  header_data
                        
%type  <task>    task
%type  <header>  header
%type  <body>    body


%{
    int yyprint(FILE *file, int type, YYSTYPE value);
%}


%%

tasks  :{
	   printf("START\n");
           $$ = new_task_list();
           yydebug=1;
        }
        | tasks EOFM
        {
          printf("\n\nTASKS LIST:\n");
          print_tasks($1);
          printf("END\n");
          YYACCEPT;
        }
        | tasks task {
            $$ = add_task_to_list($1, $2);
            
	}
        ;

task	: header body {
		$$ = new_task($1, $2);
                print_task($$);
	}
	;

eoh	: NEWLINE
	;

tagline : { $$=NULL; }
        | TAG { $$=$1; printf("{TAG: %s}", $1); }
        ;
        
header	: task_level header_data tagline eoh {
		$$ = add_level_to_header($2, $1);
                $$ = add_tag_to_header($$, $3);
	}
	;

header_data
        : { $$ = new_task_header(); } 
        | header_data textex { $$=append_caption_to_header($1, $2); }
        | header_data class  { $$=add_state_to_header($1, $2); }
        | header_data priority { $$=add_priority_to_header($1, $2); } 
        | header_data completion { $$=add_completion_to_header($1, $2); }
        ;

completion
        : CHECKBOX {
              printf("{COMP: %08x}", $1);
              $$ = $1;
        }
        ;
        
task_level	: TASK { $$ = $1 }
		;

caption		: string {
		     printf("{CAP: %s}", $1);
                     $$=$1;
                }
		;


                
class		: KEYWORD {
		      printf("{Class: %s}", $1);
    		      $$=$1;
                }
		;


priority	: PRIORITY {
			printf("{Prio: %c}", $1);
                        $$ = $1;
		}
		;
                
body	:                     { printf("{B:s}"); $$ = new_task_body(NULL); }
        |       body textline { printf("{B:a}"); $$ = add_text_to_body($1, $2); }
        |       body SCHEDULED maytext DATE    { $$ = add_date_to_body($1, $4, 1)}
        |       body SCHEDULED maytext DATEACT { $$ = add_date_to_body($1, $4, 2)}
        |       body CLOSED    maytext DATE    { $$ = add_date_to_body($1, $4, 3)}
        |       body CLOSED    maytext DATEACT { $$ = add_date_to_body($1, $4, 4)}
        |       body CLOCK     maytext DATEACTRANGE { $$ = $1; } /* fix later */
        |       body CLOCK     maytext DATERANGE    { $$ = $1; } /* fix later */
        |       body DATE      { $$ = add_date_to_body($1, $2, 5)}
        |       body DATEACT   { $$ = add_date_to_body($1, $2, 6)}
	;

string	: { $$ = NULL; }
        |       string textex {
                  printf("{ST:D:%s => %s}", $1, $2);
                  $$=append_string($1, $2);
        }
	;

maytext : 
        | TEXT
        ;
        
textex  : TEXT      { $$ = $1; }
        | KEYWORD   { $$ = $1; }
        ;
        
textnt  : TEXT      { $$ = $1; }
        | KEYWORD   { $$ = $1; }
        | NEWLINE   { $$ = $1; }
        ;
        
textline : { $$ = NULL; }
        | textline textnt {
                  printf("{ST:D:%s => %s}", $1, $2);
                  $$=append_string($1, $2);
        }
        ;
        

text	: { $$ = NULL; }
        |       text textline {
	          printf("{Te}");
		  $$=append_string($1, $2);
		}
	;

%%
